<?php
/**
 * Created by PhpStorm.
 * User: ari
 * Date: 12/3/14
 * Time: 4:37 PM
 */
namespace BC\User;

use BC\SiteIndex;
use BC\User\Session\UserSession;
use CPath\Build\IBuildable;
use CPath\Build\IBuildRequest;
use CPath\Render\HTML\Element\Form\HTMLForm;
use CPath\Render\HTML\Element\Form\HTMLSubmit;
use CPath\Render\HTML\Element\HTMLElement;
use CPath\Request\Exceptions\RequestException;
use CPath\Request\Executable\IExecutable;
use CPath\Request\Form\IFormRequest;
use CPath\Request\IRequest;
use CPath\Request\Session\ISessionRequest;
use CPath\Request\Validation\Exceptions\ValidationException;
use CPath\Response\Common\RedirectResponse;
use CPath\Response\IResponse;
use CPath\Route\IRoutable;
use CPath\Route\RouteBuilder;

class Logout implements IRoutable, IExecutable, IBuildable
{
	const PATH_FORMAT = '/logout/%s';
	const PATH_FORMAT2 = '/user/%s/logout';

	const FORM_ACTION = 'logout';
	const CLS_FORM = 'form-logout';

	const CLS_FIELD_FINGERPRINT= 'field-fingerprint';

	const CLS_FIELD_SUBMIT = 'field-submit';

	const CLS_FIELDSET_SUBMIT = 'fieldset-submit';


	const PARAM_FINGERPRINT = 'fingerprint';
	const PARAM_SUBMIT = 'submit';

	/**
	 * Execute a command and return a response. Does not render
	 * @param IRequest $Request
	 * @throws \CPath\Request\Validation\Exceptions\ValidationException
	 * @throws \CPath\Request\Exceptions\RequestException
	 * @return IResponse the execution response
	 */
	function execute(IRequest $Request) {
		$SessionRequest = $Request;
		if(!$SessionRequest instanceof ISessionRequest)
			throw new RequestException("No session present");
		if(!$SessionRequest->hasSessionCookie())
			throw new RequestException("No session cookie present");

		if(!UserSession::hasSession($SessionRequest)) {
			$SessionRequest->destroySession();
			throw new RequestException("Session set without user data. destroying session...");
		}
		$UserSession = UserSession::fromSession($SessionRequest);
		$sessionID = $UserSession::getSessionIDFromSession($SessionRequest);

//		$action = sprintf(self::PATH_FORMAT2, $this->getUserFingerprint());
		$Form = new HTMLForm('POST', $Request->getPath(), self::CLS_FORM,

//			new HTMLMetaTag(HTMLMetaTag::META_TITLE, 'User Public Key - ' . $Session->getUser()->getUserID()),

			//new HTMLHeaderScript(__DIR__ . '\assets\form-' . self::FORM_ACTION . '.js'),
			//new HTMLHeaderStyleSheet(__DIR__ . '\assets\form-' . self::FORM_ACTION . '.css'),

			new HTMLElement('legend', 'content-title', 'Log out - ' . $sessionID),

			new HTMLElement('fieldset', self::CLS_FIELDSET_SUBMIT,
				new HTMLElement('legend', 'legend-submit toggle', "Submit"),

				"Log out of the current session\n",
				new HTMLSubmit(self::PARAM_SUBMIT, 'Logout')
			)
		);

		if(!$Request instanceof IFormRequest)
			return $Form;

		if(!$SessionRequest->destroySession())
			throw new ValidationException($Form, "Could not end session");

		return new RedirectResponse($UserSession::getRequestPath($UserSession->getGrantFingerprint(), UserSession::COMMAND_LOGIN),
			"User logged out successfully - " . $sessionID, 5);
	}

	// Static

	/**
	 * Route the request to this class object and return the object
	 * @param IRequest $Request the IRequest inst for this render
	 * @param array|null $Previous all previous response object that were passed from a handler, if any
	 * @param null|mixed $_arg [varargs] passed by route map
	 * @return void|bool|Object returns a response object
	 * If nothing is returned (or bool[true]), it is assumed that rendering has occurred and the request ends
	 * If false is returned, this static handler will be called again if another handler returns an object
	 * If an object is returned, it is passed along to the next handler
	 */
	static function routeRequestStatic(IRequest $Request, Array &$Previous = array(), $_arg = null) {
		return new Logout();
	}


	/**
	 * Handle this request and render any content
	 * @param IBuildRequest $Request the build request inst for this build session
	 * @return void
	 * @build --disable 0
	 * Note: Use doctag 'build' with '--disable 1' to have this IBuildable class skipped during a build
	 */
	static function handleBuildStatic(IBuildRequest $Request) {
		$RouteBuilder = new RouteBuilder($Request, new SiteIndex());
//		$RouteBuilder->writeRoute('ANY ' . sprintf(self::PATH_FORMAT, ':' . self::PARAM_FINGERPRINT), __CLASS__);
		$RouteBuilder->writeRoute('ANY ' . sprintf(self::PATH_FORMAT, ''), __CLASS__, IRequest::MATCH_SESSION_ONLY);
		$RouteBuilder->writeRoute('ANY ' . sprintf(self::PATH_FORMAT2, ':' . self::PARAM_FINGERPRINT), __CLASS__);
	}
}